/*
 * @Author: Wangjun
 * @Date: 2021-05-15 22:43:19
 * @LastEditTime: 2022-09-25 22:22:10
 * @LastEditors: Wangjun
 * @Description:
 * @FilePath: \golib\lz4file\lz4file.go
 * hnxr
 */
package lz4file

import (
	"bytes"
	"encoding/base64"
	"io/ioutil"
	"os"

	"github.com/pierrec/lz4"
)

/**
 * @description: 解码
 * @param {[]byte} b
 * @return {*}
 */
func Decode(b []byte) (data []byte, err error) {
	buf := bytes.NewBuffer(nil)
	zw := lz4.NewWriter(buf)
	zw.BlockMaxSize = 1024 * 1024
	zw.CompressionLevel = 0

	_, err = zw.Write(b)
	if err != nil {
		return
	}
	zw.Close()
	data = buf.Bytes()
	return
}

/**
 * @description: lz4 编码
 * @param {[]byte} b
 * @return {*}
 */
func Encode(b []byte) (data []byte, err error) {
	zr := lz4.NewReader(bytes.NewBuffer(b))
	data, err = ioutil.ReadAll(zr)
	return
}

//EncodeToBase64 压缩后编码到base64
func EncodeToBase64(b []byte, level int) (data string, err error) {
	buf := bytes.NewBuffer(nil)
	zw := lz4.NewWriter(buf)
	zw.BlockMaxSize = 1024 * 1024
	zw.CompressionLevel = 0

	_, err = zw.Write(b)
	if err != nil {
		return
	}
	zw.Close()
	if err != nil {
		return
	}
	data = base64.StdEncoding.EncodeToString(buf.Bytes())
	return
}

//DecodeFromBase64 先解码再加压缩
func DecodeFromBase64(s string) (data []byte, err error) {
	data, err = base64.StdEncoding.DecodeString(s)
	if err != nil {
		return
	}
	zr := lz4.NewReader(bytes.NewBuffer(data))
	data, err = ioutil.ReadAll(zr)
	return
}

//SaveLz4File 保存
func SaveLz4File(file string, data []byte) (err error) {
	f, err := os.Create(file + ".tmp")
	if err != nil {
		return
	}
	zw := lz4.NewWriter(f)
	zw.BlockMaxSize = 1024 * 1024
	zw.CompressionLevel = 0

	_, err = zw.Write(data)
	if err != nil {
		return
	}
	zw.Close()
	f.Close()
	if err != nil {
		return
	}

	path := file + ".tmp"
	err = os.Rename(path, file)
	return
}

//LoadLz4File 从文件中加载
func LoadLz4File(file string) (data []byte, err error) {
	f, err := os.Open(file)
	if err != nil {
		return
	}
	defer f.Close()
	zr := lz4.NewReader(f)
	data, err = ioutil.ReadAll(zr)
	return
}
